import { ForbiddenException, Injectable, UnauthorizedException } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import { UserService } from "../user/user.service";
import * as argon2 from "argon2";
import { Profile } from "../user/profile.entity";
import { User } from "../user/user.entity";
import { RedisService } from "../redis/redis.services";
import { ConfigService } from "@nestjs/config";
import { ConfigEnum } from "src/enum/config.enum";

@Injectable()
export class AuthService {
  constructor(
    private userService: UserService,
    private jwtService: JwtService,
    private redisService: RedisService, // 注入 Redis 服务
    private configService: ConfigService, // 注入配置服务
  ) {}

  /**
   * 登录
   *
   * @param password 密码
   * @param usernameOrEmail 用户名/邮箱
   * @returns
   * */
  async signin(password: string, usernameOrEmail: string) {
    let userByUsername: User | null | undefined = null;
    let userByEmail: User | null | undefined = null;

    // 捕获用户名查询异常，防止服务器崩溃
    try {
      userByUsername = await this.userService.find(usernameOrEmail);
    } catch (error) {
      // 忽略查询异常，继续执行
      userByUsername = null;
    }

    // 捕获邮箱查询异常，防止服务器崩溃
    try {
      userByEmail = await this.userService.findByEmail(usernameOrEmail);
    } catch (error) {
      // 忽略查询异常，继续执行
      userByEmail = null;
    }

    if (!userByUsername && !userByEmail) {
      throw new ForbiddenException("用户不存在");
    }

    const user = (userByUsername || userByEmail)!;

    const isPasswordValid = await argon2.verify(user.password, password);
    if (!isPasswordValid) {
      throw new ForbiddenException(`用户名或者邮箱或者密码错误`);
    }

    // 生成 JWT token
    const token = await this.jwtService.signAsync({ sub: user.id, username: user.username });

    // 获取过期时间（秒）
    const expiresInSeconds = this.configService.get<number>(ConfigEnum.JWT_EXPIRES_IN, 86400);

    // 将 token 存储到 Redis，key 格式: token:userId
    const tokenKey = `token:${user.id}`;
    await this.redisService.setWithTTL(tokenKey, token, expiresInSeconds);

    return token;
  }

  /**
   * 注册
   *
   * @param username 用户名
   * @param password 密码
   * @returns
   * */
  async singup(username: string, password: string, email: string) {
    const user = await this.userService.find(username);
    if (user) {
      throw new ForbiddenException("用户已存在");
    }
    const res = await this.userService.create({
      username,
      password,
      profile: {
        email,
      } as Profile,
      roles: [],
    });
    return res;
  }

  /**
   * 登出
   * 从 Redis 中删除 token
   *
   * @param userId 用户 ID
   * @returns
   * */
  async signout(userId: number) {
    const tokenKey = `token:${userId}`;
    await this.redisService.del(tokenKey);
    return { message: "登出成功" };
  }

  /**
   * 验证 token 是否在 Redis 中存在
   *
   * @param userId 用户 ID
   * @param token JWT token
   * @returns
   * */
  async validateToken(userId: number, token: string): Promise<boolean> {
    const tokenKey = `token:${userId}`;
    const storedToken = await this.redisService.get(tokenKey);
    console.log("storedToken", storedToken);
    console.log("================================================");
    console.log("token", token);
    return storedToken === token;
  }
}
